package com.bang.daybreak.common.mybatisplus;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.TableInfoHelper;
import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils;
import com.bang.daybreak.common.enums.OracleSqlEnum;
import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator;
import org.apache.ibatis.executor.keygen.KeyGenerator;
import org.apache.ibatis.executor.keygen.NoKeyGenerator;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;

import java.util.List;
import java.util.function.Predicate;

/**
 * 批量插入oracle数据
 *
 * @author : wdj
 * @since : 2019/5/3 0003 下午 17:57
 * @version 1.0
 */
public class InsertBatchOracleSomeColumn extends AbstractMethod {
    private static final String MAPPER_METHOD = "insertBatchOracleSomeColumn";
    private Predicate<TableFieldInfo> predicate;

    public InsertBatchOracleSomeColumn(Predicate<TableFieldInfo> predicate) {
        Assert.notNull(predicate, "this predicate can not be null !", new Object[0]);
        this.predicate = predicate;
    }

    /**
     * 批量插入oralce数据
     *
     * @param mapperClass
     * @param modelClass
     * @param tableInfo
     * @return
     */
    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        KeyGenerator keyGenerator = new NoKeyGenerator();
        OracleSqlEnum sqlMethod = OracleSqlEnum.INSERT_ONE;

        // String insertSqlColumn = tableInfo.getSomeInsertSqlColumn(this.predicate); old version，3.0.7.1.老版本写法.
        List<TableFieldInfo> fieldList = tableInfo.getFieldList();
        String insertSqlColumn = tableInfo.getKeyInsertSqlColumn(false) + this.filterTableFieldInfo(fieldList, this.predicate, TableFieldInfo::getInsertSqlColumn, "");


        String columnScript = "(" + insertSqlColumn.substring(0, insertSqlColumn.length() - 1) + ")";

        //  String insertSqlProperty = tableInfo.getSomeInsertSqlProperty("et.", this.predicate); old version，3.0.7.1.老版本写法.
        String insertSqlProperty = tableInfo.getKeyInsertSqlProperty("et.", false) + this.filterTableFieldInfo(fieldList, this.predicate, (i) -> {
            return i.getInsertSqlProperty("et.");
        }, "");

        insertSqlProperty = "(SELECT " + insertSqlProperty.substring(0, insertSqlProperty.length() - 1) + "  FROM DUAL)";

        String valuesScript = SqlScriptUtils.convertForeach(insertSqlProperty, "list", (String) null, "et", "UNION ALL");
        String keyProperty = null;
        String keyColumn = null;
        if (StringUtils.isNotEmpty(tableInfo.getKeyProperty())) {
            if (tableInfo.getIdType() == IdType.AUTO) {
                keyGenerator = new Jdbc3KeyGenerator();
                keyProperty = tableInfo.getKeyProperty();
                keyColumn = tableInfo.getKeyColumn();
            } else if (null != tableInfo.getKeySequence()) {
                keyGenerator = TableInfoHelper.genKeyGenerator(tableInfo, this.builderAssistant, sqlMethod.getMethod(), this.languageDriver);
                keyProperty = tableInfo.getKeyProperty();
                keyColumn = tableInfo.getKeyColumn();
            }
        }

        String sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), columnScript, valuesScript);
        SqlSource sqlSource = this.languageDriver.createSqlSource(this.configuration, sql, modelClass);
        return this.addInsertMappedStatement(mapperClass, modelClass, "insertBatchOracleSomeColumn", sqlSource, (KeyGenerator) keyGenerator, keyProperty, keyColumn);
    }
}
